﻿using GamFi.API.Application.Exceptions;
using GamFi.API.Application.Interfaces;
using GamFi.API.Application.Resources;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;

namespace GamFi.API.Application.Features.Queries.Purchase.PostBuyToken;

public class PostBuyTokenCommandHandler(
    IDbContext dbContext,
    IUserContext userContext,
    IStringLocalizer<ExceptionMessages> localizer)
    : IRequestHandler<PostBuyTokenCommand, Unit>
{
    public async Task<Unit> Handle(PostBuyTokenCommand request, CancellationToken cancellationToken)
    {
        if (request is null)
            throw new RequestException(localizer[nameof(RequestException.RequestIsEmpty)]);

        if (userContext.CurrentUserId is null)
            throw new UserException(localizer[nameof(UserException.PermissionDenied)]);
        
        var token = await dbContext.Tokens.FirstOrDefaultAsync(t => t.Id == request.TokenId, cancellationToken);

        if (token is null)
            throw new TokenException(localizer[nameof(TokenException.TokenIsNotExist)]);

        var wallet =
            await dbContext.Wallets.FirstOrDefaultAsync(w => w.UserId == userContext.CurrentUserId, cancellationToken);

        if (wallet is null)
            throw new WalletException(localizer[nameof(WalletException.WalletNotFound)]);

        if (wallet.Balance < token.TokenPrice)
            throw new WalletException(localizer[nameof(WalletException.NotEnoughBalance)]);

        wallet.Balance -= token.TokenPrice;

        token.TotalRaise += token.TokenPrice;

        var purchase = new Domain.Entities.Purchase
        {
            Amount = token.TokenPrice,
            Date = DateTime.UtcNow,
            TokenId = token.Id,
            WalletId = wallet.Id,
        };

        await dbContext.Purchases.AddAsync(purchase, cancellationToken);
        await dbContext.SaveChangesAsync(cancellationToken);

        return Unit.Value;
    }
}